package com.seek.inter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.constants.AlipayServiceEnvConstants;
import com.lianlianpay.bean.NotifyResponseBean;
import com.lianlianpay.constant.PaymentConstant;
import com.lianlianpay.constant.PaymentStatusEnum;
import com.lianlianpay.util.SignUtil;
import com.lianpay.api.util.TraderRSAUtil;
import com.seek.authcheck.constants.NoticeConstant;
import com.seek.common.handler.SpringContextHolder;
import com.seek.model.entity.TLoanRepayment;
import com.seek.service.LoanRePayMentService;
import com.seek.service.LoanService;
import com.seek.util.CommonUtil;
import com.seek.util.JsonUtil;

/**
 * 接收第三方回调通知
 * Created by weh on 2017/7/4.
 */
@Controller
@RequestMapping("/tradepayapi")
public class CallBackController {
	private  LoanService  loanService = (LoanService)SpringContextHolder.getBean("loanService");
	private  LoanRePayMentService loanRePayMentService = (LoanRePayMentService)SpringContextHolder.getBean("loanRePayMentService");
	//private  BizFlowService bizFlowService = (BizFlowService)SpringContextHolder.getBean("bizFlowService");
	//private CompanyAgentMoneyService companyAgentMoneyService = (CompanyAgentMoneyService)SpringContextHolder.getBean("companyAgentMoneyService");
	
	private static Logger logger = LoggerFactory.getLogger(CallBackController.class);

	/**
	 * 连连app还款或续借异步回调
	 **/
	@RequestMapping(value = "/repayment", method = RequestMethod.POST)
	public void getAuthNotice(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String reqStr = CallBackController.getRequestStr(request);
		logger.info("==========接收连连支付还款回调内容:" + reqStr);
		JSONObject reqJson = JSONObject.parseObject(reqStr);

		NotifyResponseBean responseBean = new NotifyResponseBean();
		// 验证签名
		boolean signCheck = TraderRSAUtil.checksign(PaymentConstant.PUBLIC_KEY_ONLINE, SignUtil.genSignData(reqJson),reqJson.getString("sign"));
		if (!signCheck) {
			// 传送数据被篡改，可抛出异常，再人为介入检查原因
			logger.error("返回结果验签异常,可能数据被篡改");
			responseBean.setRet_code("9999");
			responseBean.setRet_msg("验签失败");
			CallBackController.writeBack(response, responseBean);
			return;
		}

		responseBean.setRet_code("0000");
		responseBean.setRet_msg("交易成功!!!");
		// 自己内部订单号
		String repayId = reqJson.getString("no_order");
		// 判断该内部订单号是否在之前已经接收过回调，如果已回调过则直接返回
		TLoanRepayment repayment = loanRePayMentService.findById(CommonUtil.getLongValue(repayId));
		if (repayment != null && repayment.getPayStatus()<1){
			try{
				if (reqJson.getString("result_pay").equals(PaymentStatusEnum.PAYMENT_SUCCESS.getValue())) {
					String payNo = reqJson.getString("oid_paybill");
					// 执行具体的业务
					loanService.loanPayBack(repayment, payNo);
				}else{
					repayment.setPayStatus(2);//失败
					repayment.setPayNo(reqJson.getString("oid_paybill"));
					repayment.setPayTime(new Date());
					repayment.setErrMsg(null);// 连连回调中未标注失败原因
					repayment.setRefreshStatus(1); // 不需要自动任务再去连连刷新支付状态
					loanRePayMentService.update(repayment);
				}
			}catch(Exception e){
				// 如果执行有异常，再执行多少次也是失败，所以告诉第三方我们这边接收到了，不用再发了
				logger.error(e.getMessage());
			}
		}
		CallBackController.writeBack(response, responseBean);
	}

  /**
	 * 连连放款异步回调
	 */
	@RequestMapping(value = "/receiveNotify" ,method = RequestMethod.POST)
	@ResponseBody
	public void receiveNotify(HttpServletRequest request,HttpServletResponse response) throws Exception {
		 logger.info("============================================lianlianPayNotify======================================");
		 String reqStr = CallBackController.getRequestStr(request);
		 logger.info("============================================lianlianPayNotify:{}",reqStr);
		JSONObject reqJson = (JSONObject) JSON.parse(reqStr);
		logger.info("============================================reqJson:{}",reqJson);
		boolean signCheck = TraderRSAUtil.checksign(PaymentConstant.PUBLIC_KEY_ONLINE,
				SignUtil.genSignData(reqJson), reqJson.getString("sign"));//验签
		NotifyResponseBean responseBean = new NotifyResponseBean();
		if (!signCheck) {//失败
			// 传送数据被篡改，可抛出异常，再人为介入检查原因
			logger.error("返回结果验签异常,可能数据被篡改");
			// 回调内容先验签，再处理相应逻辑
			responseBean.setRet_code("9999");
			responseBean.setRet_msg("未知异常");
			CallBackController.writeBack(response, responseBean);
			return;
		}
		responseBean.setRet_code("0000");
		responseBean.setRet_msg("交易成功");
		String resultPay = reqJson.getString("result_pay");//SUCCESS 付款成功 FAILURE 付款失败 CANCEL 付款退款
		logger.info("============================================resultPay:{}",resultPay);
		String oidPaybill = reqJson.getString("oid_paybill");//第三方订单号
		logger.info("============================================oidPaybill:{}",oidPaybill);
		String orderNo = reqJson.getString("no_order");//我们生成的流水号
		logger.info("============================================orderNo:{}",orderNo);
		String infoOrder = reqJson.getString("info_order");//第三方返回的错误信息
		logger.info("============================================infoOrder:{}",infoOrder);
		//具体业务逻辑
		loanService.automaticLoan(resultPay, oidPaybill, orderNo,infoOrder);
//		//根据订单号，查询tloan，取出 一级，二级代理商的信息，进行插入
//		Map<String,Object> loanMap = loanService.findOneMapBySql("select agent_id agentId,sub_agent_id subAgentId,agent_money agentMoney,sub_agent_money subAgentMoney,id loanId,customer_id customerId from t_loan where order_no = ?",new Object[]{orderNo});
//		long agentId = CommonUtil.getLongValue(loanMap.get("agentId"));
//		long subAgentId = CommonUtil.getLongValue(loanMap.get("subAgentId"));
//		int[] companyAgentMoney = companyAgentMoneyService.getAgentMoneySetting(agentId, subAgentId, 2);
//		StringBuffer sb = new StringBuffer("update t_loan set down_type = 1 ,down_time = now(),loan_status = ? ,down_remark = ? , executionstatus= 0,agent_money = ?,sub_agent_money = ?");
//		if (resultPay.equals(PaymentStatusEnum.PAYMENT_SUCCESS.getValue())) {
//			// TODO 商户更新订单为成功，处理自己的业务逻辑
//			 sb.append(" , start_time = ? ,end_time = ?");
//			 Date start = DateUtil
//			          .getDateByString(DateUtil.dateFormat(new Date(), DateUtil.DATE_FORMAT_YMD),
//			              DateUtil.DATE_FORMAT_YMD);//开始时间
//			      Date end = DateUtil.dateAdd(DateUtil.DATE_INTERVAL_DAY, start, 7);
//			      end = DateUtil.dateAdd(DateUtil.DATE_INTERVAL_SECOND, end, -1);//放款6天后的时间
//			      list.add(3);
//				  list.add(PaymentStatusEnum.PAYMENT_SUCCESS.getDesc());
//			      list.add(start);
//			      list.add(end);
//		} else if (resultPay.equals(PaymentStatusEnum.PAYMENT_FAILURE.getValue())) {
//			// TODO 商户更新订单为失败，处理自己的业务逻辑
//			  list.add(4);
//			  list.add(PaymentStatusEnum.PAYMENT_FAILURE.getDesc());
//		}
//		
//		list.add(companyAgentMoney[0]);
//		list.add(companyAgentMoney[1]);
//		list.add(orderNo);
//		sb.append(" where order_no= ? ");
//		//这个是异步回调，所以没有loan_id，除非在访问第三放的时候，把参数值丢过去，第三方在异步返回
//		loanService.executeUpdate(sb.toString(),list.toArray(new Object[]{list.size()})); 
//		//判断是否有代理商
//		if(MapUtils.isNotEmpty(loanMap)&&agentId>0){
//			
//			companyAgentMoneyService.addAgentMoneyLog(agentId,subAgentId,companyAgentMoney[0],companyAgentMoney[1],
//					                                  CommonUtil.getLongValue(loanMap.get("loanId")), 
//					                                  CommonUtil.getLongValue(loanMap.get("customerId")),2);
//		}
//		String sql = "update t_biz_flow set modify_time=now(),status=?,org_biz_no=?,org_code =? where biz_no = ? and deleted=0";
//		bizFlowService.updateBizFlow(sql,new Object[]{1,oidPaybill,"LIANLIANFANGKUAN",orderNo});
		//回调内容先验签，再处理相应逻辑
		CallBackController.writeBack(response, responseBean);
	}

	/**
	 * 阿里还款异步回调
	 * 阿里回调，需要返回给阿里SUCCESS字符串
	 **/
	@RequestMapping(value = "/alirepayment")
	public String alirepayment(HttpServletRequest request,HttpServletResponse response) throws Exception {
		Map<String,String> params = new HashMap<String,String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
		    String name = (String) iter.next();
		    String[] values = (String[]) requestParams.get(name);
		    String valueStr = "";
		    for (int i = 0; i < values.length; i++) {
		        valueStr = (i == values.length - 1) ? valueStr + values[i]
		                    : valueStr + values[i] + ",";
		  }
		  //乱码解决，这段代码在出现乱码时使用。
		  //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
		  params.put(name, valueStr);
		 }
		//切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
		//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
		
		boolean flag = AlipaySignature.rsaCheckV1(params,AlipayServiceEnvConstants.ZFB_PUBLIC_KEY,
				AlipayServiceEnvConstants.CHARSET, AlipayServiceEnvConstants.SIGN_TYPE);
		logger.info("aliresparams:" + params);
		
		logger.info("=======================阿里延签状态值=================:" + flag);
		if (!flag) {// 失败
			// 传送数据被篡改，可抛出异常，再人为介入检查原因
			logger.info("返回结果验签异常,可能数据被篡改");
			// 回调内容先验签，再处理相应逻辑
			return "success";
		}
		// 自己内部订单号
		String repayId = params.get("out_trade_no");
		logger.info("repayId{}",repayId);
		// 判断该内部订单号是否在之前已经接收过回调，如果已回调过则直接返回
		TLoanRepayment repayment = loanRePayMentService.findById(CommonUtil.getLongValue(repayId));
		logger.info("repayment{}",JSON.toJSONString(repayment));
		if (repayment != null && repayment.getPayStatus()<1){
			try{
				logger.info("params.get(trade_status){}",params.get("trade_status"));
				if (params.get("trade_status").equals("TRADE_SUCCESS")) {
					String payNo = params.get("trade_no");
					logger.info("params.get(out_biz_no){}",params.get("trade_no"));
					// 执行具体的业务
					loanService.loanPayBack(repayment, payNo);
				}else{
					repayment.setPayStatus(2);//失败
					repayment.setPayNo(params.get("out_biz_no"));
					repayment.setPayTime(new Date());
					repayment.setErrMsg(null);// 
					repayment.setRefreshStatus(1);
					loanRePayMentService.update(repayment);
				}
			}catch(Exception e){
				// 如果执行有异常，再执行多少次也是失败，所以告诉第三方我们这边接收到了，不用再发了
				logger.error(e.getMessage());
			}
		}
		return "success";
	}

	public static String getRequestStr(HttpServletRequest request) throws IOException {
		InputStream in = request.getInputStream();
		byte[] b = new byte[10240];
		int len;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		while ((len = in.read(b)) > 0) {
			baos.write(b, 0, len);
		}
		String bodyText = new String(baos.toByteArray(), NoticeConstant.CHARSET_UTF8);
		return bodyText;
	}

	// 向第三方回调输出
	public static void writeBack(HttpServletResponse response, NotifyResponseBean responseBean) throws Exception {
		response.setCharacterEncoding(NoticeConstant.CHARSET_UTF8);
		response.setContentType(NoticeConstant.CONTENT_TYPE);
		response.getOutputStream().write(JsonUtil.toJson(responseBean).getBytes(NoticeConstant.CHARSET_UTF8));
	}
}
